#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

// WiFi & 网络相关
#include "hi_wifi_api.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"  // 新增：DNS解析支持（解决Broker域名解析失败）

// 硬件 IO 相关
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_gpio.h"
#include "hi_pwm.h"
#include "hi_errno.h"

// MQTT 相关
#include "mqtt_ohos.h"
#include "MQTTClient.h"

// --- 硬件引脚配置 ---
#define LED_TEST_GPIO 11       // LED (输出)
#define SKEW_DETECT_GPIO 10    // 传感器 (输入)
#define BEEP_PIN 9             // 蜂鸣器 (PWM0)

// --- WiFi 配置（请确保 SSID/密码正确）---
#define WIFI_SSID     "***"
#define WIFI_PASSWORD "z012345678123"

// --- MQTT 配置（保留原有 Broker 和认证）---
#define MQTT_BROKER   "broker.emqx.io"  
#define MQTT_PORT     1883
#define MQTT_TOPIC    "24iot01/team12"
#define MQTT_CLIENTID "mqttx_abc53a1f"  // 优化：添加唯一后缀，避免冲突
#define MQTT_USER     "device12_skew_v1"
#define MQTT_PASS     "123456"

// --- 全局变量 ---
static int g_wifi_connected = 0;
static struct netif *g_lwip_netif = NULL;
static MQTTClient mq_client;
static Network n;
static unsigned char *mqtt_buf;
static unsigned char *mqtt_readbuf;
static int buf_size = 4096;
static MQTTPacket_connectData mqtt_conn_data;  // 全局化，方便重连

// 逻辑状态宏
#define SKEW_DETECT_ON 1
#define SKEW_DETECT_OFF 0
static const uint16_t ALARM_FREQ_DIV = 38223; 

// --- 硬件初始化（优化：默认关闭蜂鸣器，避免误触发）---
static void HardwareInit(void) {
    // LED (GPIO 11)
    IoTGpioInit(LED_TEST_GPIO);
    hi_io_set_func(LED_TEST_GPIO, HI_IO_FUNC_GPIO_11_GPIO); 
    IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT);
    hi_io_set_pull(LED_TEST_GPIO, HI_IO_PULL_UP);
    IoTGpioSetOutputVal(LED_TEST_GPIO, 1); // 优化：默认灭（原 0 是点亮，容易误触发）

    // 传感器 (GPIO 10)
    IoTGpioInit(SKEW_DETECT_GPIO);
    hi_io_set_func(SKEW_DETECT_GPIO, HI_IO_FUNC_GPIO_10_GPIO);
    IoTGpioSetDir(SKEW_DETECT_GPIO, IOT_GPIO_DIR_IN);
    hi_io_set_pull(SKEW_DETECT_GPIO, HI_IO_PULL_UP);

    // 蜂鸣器 (GPIO 9 -> PWM0)
    hi_io_set_func(BEEP_PIN, HI_IO_FUNC_GPIO_9_PWM0_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM0);
    hi_pwm_set_clock(PWM_CLK_XTAL);
    AlarmOff(); // 初始化关闭蜂鸣器
}

// --- 蜂鸣器控制 ---
static void AlarmOn(void) {
    hi_pwm_start(HI_PWM_PORT_PWM0, ALARM_FREQ_DIV / 2, ALARM_FREQ_DIV);
}
static void AlarmOff(void) {
    hi_pwm_stop(HI_PWM_PORT_PWM0);
}

// --- WiFi 事件回调（优化：添加 DHCP 成功日志，确认IP有效性）---
void wifi_event_cb(const hi_wifi_event *hisi_event) {
    if (hisi_event == NULL) return;
    switch (hisi_event->event) {
        case HI_WIFI_EVT_CONNECTED:
            printf("WiFi Connected!\n");
            netifapi_dhcp_start(g_lwip_netif);
            g_wifi_connected = 1;
            break;
        case HI_WIFI_EVT_DISCONNECTED:
            printf("WiFi Disconnected!\n");
            g_wifi_connected = 0;
            break;
        case HI_WIFI_EVT_DHCP_DONE:  // 新增：DHCP分配IP成功事件
            {
                ip4_addr_t ipaddr, netmask, gw;
                netifapi_netif_get_addr(g_lwip_netif, &ipaddr, &netmask, &gw);
                printf("DHCP Done! IP: %s, GW: %s\n", 
                       ip4_addr_ntoa(&ipaddr), ip4addr_ntoa(&gw));
                // 验证DNS是否可用（关键：解决Broker域名解析失败）
                ip_addr_t dns_ip;
                dns_getserver(0, &dns_ip);
                printf("DNS Server: %s\n", ip4addr_ntoa(&dns_ip));
            }
            break;
        default: 
            printf("WiFi Event: %d\n", hisi_event->event);
            break;
    }
}

// --- 连接 WiFi（优化：添加重试机制，补充SSID/密码长度）---
int Wifi_Connect(void) {
    int ret;
    char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
    int len = sizeof(ifname);
    
    // 启动STA模式（重试3次，避免单次失败）
    for (int i = 0; i < 3; i++) {
        ret = hi_wifi_sta_start(ifname, &len);
        if (ret == HISI_OK) break;
        printf("WiFi STA Start Failed (retry %d), ret: %d\n", i+1, ret);
        sleep(1);
    }
    if (ret != HISI_OK) return -1;

    hi_wifi_register_event_callback(wifi_event_cb);
    g_lwip_netif = netifapi_netif_find(ifname);
    if (g_lwip_netif == NULL) {
        printf("Find WiFi Netif Failed!\n");
        return -1;
    }

    hi_wifi_assoc_request assoc_req = {0};
    assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK;
    memcpy(assoc_req.ssid, WIFI_SSID, strlen(WIFI_SSID));
    memcpy(assoc_req.key, WIFI_PASSWORD, strlen(WIFI_PASSWORD));
    assoc_req.ssid_len = strlen(WIFI_SSID);  // 新增：补充SSID长度（兼容部分SDK）
    assoc_req.key_len = strlen(WIFI_PASSWORD); // 新增：补充密码长度
    
    printf("Connecting to WiFi: %s ...\n", WIFI_SSID);
    // 连接WiFi（重试3次）
    for (int i = 0; i < 3; i++) {
        ret = hi_wifi_sta_connect(&assoc_req);
        if (ret == HISI_OK) break;
        printf("WiFi Connect Failed (retry %d), ret: %d\n", i+1, ret);
        sleep(2);
    }
    return (ret == HISI_OK) ? 0 : -1;
}

// --- 发布 MQTT 消息（优化：检查MQTT连接状态）---
void Publish_Msg(char *payload) {
    if (!g_wifi_connected || !mq_client.isconnected) {
        printf("Publish Failed: WiFi/MQTT Disconnected\n");
        return;
    }
    
    MQTTMessage message;
    message.qos = 0;
    message.retained = 0;
    message.payload = (void *)payload;
    message.payloadlen = strlen(payload);
    
    int rc = MQTTPublish(&mq_client, MQTT_TOPIC, &message);
    if (rc < 0) {
        printf("MQTT Pub Failed: %d\n", rc);
    } else {
        printf("MQTT Pub Success: %s\n", payload);
    }
}

// --- MQTT 连接（独立封装，支持重试和重连）---
static int Mqtt_Connect(void) {
    if (!g_wifi_connected) {
        printf("MQTT Connect Failed: WiFi Not Ready\n");
        return -1;
    }

    // 初始化网络
    NetworkInit(&n);
    printf("Connecting to MQTT Broker: %s:%d ...\n", MQTT_BROKER, MQTT_PORT);
    
    // TCP连接（重试5次，每次间隔2秒，解决网络波动）
    int tcp_ret = -1;
    for (int i = 0; i < 5; i++) {
        tcp_ret = NetworkConnect(&n, MQTT_BROKER, MQTT_PORT);
        if (tcp_ret == 0) break;
        printf("TCP Connect Failed (retry %d), ret: %d\n", i+1, tcp_ret);
        sleep(2);
    }
    if (tcp_ret != 0) {
        printf("TCP Connect Failed After 5 Retries (Broker Unreachable?)\n");
        return -1;
    }

    // 分配MQTT缓冲区（复用已分配的缓冲区）
    if (mqtt_buf == NULL) mqtt_buf = (unsigned char *)malloc(buf_size);
    if (mqtt_readbuf == NULL) mqtt_readbuf = (unsigned char *)malloc(buf_size);
    if (mqtt_buf == NULL || mqtt_readbuf == NULL) {
        printf("MQTT Buf Malloc Failed\n");
        NetworkDisconnect(&n);
        return -1;
    }

    // 初始化MQTT客户端（优化：超时时间延长到5秒，提高容错）
    MQTTClientInit(&mq_client, &n, 5000, mqtt_buf, buf_size, mqtt_readbuf, buf_size);
    
    // MQTT连接参数（优化：适配EMQX Broker，补充关键参数）
    memset(&mqtt_conn_data, 0, sizeof(MQTTPacket_connectData));
    mqtt_conn_data = MQTTPacket_connectData_initializer;
    mqtt_conn_data.MQTTVersion = MQTTVERSION_3_1_1;  // 优化：EMQX优先支持3.1.1版本
    mqtt_conn_data.clientID.cstring = MQTT_CLIENTID;
    mqtt_conn_data.username.cstring = MQTT_USER;
    mqtt_conn_data.password.cstring = MQTT_PASS;
    mqtt_conn_data.keepAliveInterval = 60;  // 新增：心跳间隔60秒，避免Broker主动断开
    mqtt_conn_data.cleansession = 1;        // 新增：清除会话，避免重连冲突
    mqtt_conn_data.willFlag = 0;            // 禁用遗嘱消息（简化配置）

    // MQTT连接（重试3次，解决认证/协议兼容问题）
    int mqtt_ret = -1;
    for (int i = 0; i < 3; i++) {
        mqtt_ret = MQTTConnect(&mq_client, &mqtt_conn_data);
        if (mqtt_ret == 0) break;
        // 打印具体错误码，方便定位（EMQX常见错误码：4=用户名密码错误，5=无权限）
        printf("MQTT Connect Failed (retry %d), ret: %d\n", i+1, mqtt_ret);
        sleep(2);
    }
    if (mqtt_ret != 0) {
        printf("MQTT Connect Failed After 3 Retries\n");
        NetworkDisconnect(&n);
        return -1;
    }

    printf("MQTT Connected to %s Successfully!\n", MQTT_BROKER);
    return 0;
}

// --- 主任务（核心优化：重连机制 + 防抖 + 日志）---
void SkewDetectMqttTask(void *arg) {
    (void)arg;
    unsigned char ucType = 0;
    unsigned char lastType = 0; 
    unsigned char ucTypeDebounce = 0;  // 防抖用

    HardwareInit(); // 硬件初始化

    // 1. 连接WiFi（失败则退出）
    if (Wifi_Connect() != 0) {
        printf("WiFi Init Failed, Task Exit\n");
        return;
    }
    // 等待WiFi连接 + DHCP分配IP（最多等10秒，避免无限阻塞）
    int wifi_wait_cnt = 0;
    while (g_wifi_connected == 0 && wifi_wait_cnt < 10) {
        sleep(1);
        wifi_wait_cnt++;
    }
    if (g_wifi_connected == 0) {
        printf("WiFi Connect Timeout, Task Exit\n");
        return;
    }
    printf("WiFi Ready! Waiting 2s for Network Stable...\n");
    sleep(2);  // 等待网络稳定

    // 2. 初始连接MQTT
    if (Mqtt_Connect() != 0) {
        printf("Initial MQTT Connect Failed, Will Retry in Loop\n");
    }

    // 3. 循环检测（优化：防抖 + MQTT重连 + 合理延时）
    while (1) {
        // --------------------------
        // 关键优化：MQTT自动重连
        // --------------------------
        if (g_wifi_connected && !mq_client.isconnected) {
            printf("\n=== MQTT Reconnecting ===\n");
            Mqtt_Connect();  // 断开后自动重连
            sleep(1);        // 重连后稳定1秒
        }

        // --------------------------
        // 优化：传感器防抖（避免误上报）
        // --------------------------
        IoTGpioGetInputVal(SKEW_DETECT_GPIO, &ucType);
        osDelay(20);  // 防抖延时20ms（RTOS延时，不阻塞线程）
        IoTGpioGetInputVal(SKEW_DETECT_GPIO, &ucTypeDebounce);
        if (ucType != ucTypeDebounce) {
            osDelay(10);
            continue;  // 抖动，忽略本次读取
        }
        ucType = ucTypeDebounce;

        // --------------------------
        // 本地硬件反馈（保留原有逻辑）
        // --------------------------
        if (ucType == SKEW_DETECT_ON) {
            IoTGpioSetOutputVal(LED_TEST_GPIO, 0); // 低电平点亮
            AlarmOn();
        } else {
            IoTGpioSetOutputVal(LED_TEST_GPIO, 1); // 高电平熄灭
            AlarmOff();
        }

        // --------------------------
        // 状态改变上报（保留原有逻辑）
        // --------------------------
        if (ucType != lastType) {
            if (ucType == SKEW_DETECT_ON) {
                Publish_Msg("倾斜正常");
            } else {
                Publish_Msg("倾斜较大");
            }
            lastType = ucType;
        }

        // --------------------------
        // MQTT心跳（优化：延长到200ms，降低功耗）
        // --------------------------
        if (mq_client.isconnected) {
            MQTTYield(&mq_client, 200);
        } else {
            osDelay(200);  // 未连接时延长延时
        }
    }
}

// --- 任务创建（优化：栈大小调整，避免栈溢出）---
void AppEntry(void) {
    osThreadAttr_t attr;
    attr.name = "SkewDetectMqttTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 16384;  // 优化：从10240调整到16384（MQTT操作需要更大栈）
    attr.priority = osPriorityNormal;  // 优化：使用标准优先级（避免优先级过高抢占资源）

    if (osThreadNew((osThreadFunc_t)SkewDetectMqttTask, NULL, &attr) == NULL) {
        printf("Create Task Failed!\n");
    }
}

SYS_RUN(AppEntry);